<?php
/**
 * 向游戏中充值
 * @author Kerry
 *
 */
abstract class Recharge_Abstract
{
	/**
	 *
	 * 是否为调式模式
	 *
	 * **/
	const DEBUG = true;

	protected $_options = array();	//配置
	protected $_defaultSign = 'sign'; //默认签名字段
	protected $_method = 'POST'; //默认访问方法

	public function __construct($options = '')
	{
		$this->setOptions($options);
	}

	/**
	 * 检验游戏充值是否成功
	 * 各个充值类必须实现
	 * @author Kerry
	 * @param array $result
	 * @return boole
	 * **/

    public abstract function checkGameRechargeSuccess($result);

	/**
	 * 向游戏充值访问
	 *
	 * @param array $order
	 */
	public function gameRecharge($order)
	{
		$params = $this->_makeParams($order);
		$sign = $this->_makeSign($params);
		$params[$this->getSignName()] = $sign;
		$result = $this->request($this->_getRequestUrl(), $this->getMethod(), $params);

		$isSuccess = false;

		if($result['code'] == 200){ //页面请求成功
			 $isSuccess = $this->checkGameRechargeSuccess($result['response']);
		}
	    if(!$isSuccess){
	    	 $this->writeLog($params);
	    }
		return $isSuccess;
	}


	/**
	 * 设置配置信息
	 * @param array $options
	 */
	protected function setOptions($options){
		$this->_options = $options;
	}

	/**
	 * 获取全部配置信息
	 */
	protected function getOptions(){
		return $this->_options;
	}

	/**
	 * 获取配置信息
	 */
	protected function getOption($key)
	{
		return isset($this->_options[$key]) ? $this->_options[$key] : null;
	}

	/**
	 * 获取请求方法
	 */
	protected function getMethod()
	{
		return $this->_method;
	}

	protected function _makeParams(array $param)
	{
		return array();
	}
	//生成签名
	protected function _makeSign($params)
	{
		ksort($params);
		$queryString = $this->buildQuery($params);
		return md5($queryString.$this->_getSignKey);
	}

	/**
	 * 获取签名字段名称
	 */
	protected function getSignName()
	{
		return $this->_defaultSign;
	}

	/**
	 * 获取请求地址(key名称如果不同请自行在子类中定义)
	 */
	protected function _getRequestUrl()
	{
		return $this->getOption('requetUrl');
	}

	/**
	 * 获取签名key(key名称如果不同请自行在子类中定义)
	 */
	protected function _getSignKey()
	{
		return $this->getOption('signKey');
	}

	/**
	 * 数组转成字符串
	 * @param array $data
	 * @param string $prefix
	 * @param string $sep
	 * @param string $key
	 */
	protected function buildQuery($data, $prefix = '', $sep = '', $key = '')
	{
		$ret = array();
		foreach ((array) $data as $k => $v)
		{
			if (is_int($k) && $prefix != null){
				$k = rawurlencode($prefix . $k);
			}
			if ((!empty($key)) || ($key === 0))
				$k = $key . '[' . rawurlencode($k) . ']';
			if (is_array($v) || is_object($v))
			{
				array_push($ret, call_user_func(__METHOD__, $v, '', $sep, $k));
			}
			else
			{
				array_push($ret, $k . '=' . rawurlencode($v));
			}
		}
		if (empty($sep))
			$sep = '&';
		return implode($sep, $ret);
	}

	/**
	 *
	 * @param string $url
	 * @param string $method
	 * @param array $params
	 */
	protected function request($url, $method = 'GET', $params = array())
	{
		$queryString = '';
		if(!empty($params)){
			$queryString = $this->buildQuery($params);
		}

		$ci = curl_init();
	    curl_setopt($ci, CURLOPT_CONNECTTIMEOUT, 30);
	    curl_setopt($ci, CURLOPT_TIMEOUT, 30);
	    curl_setopt($ci, CURLOPT_RETURNTRANSFER, true);
	    curl_setopt($ci, CURLOPT_HEADER, false);

	    $method = strtoupper($method);
		switch ($method)
		{
			case 'POST' :
				curl_setopt($ci, CURLOPT_POST, TRUE);
				if(!empty($queryString)){
					curl_setopt($ci, CURLOPT_POSTFIELDS, $queryString);
				}
				break;
			case 'DELETE' :
				curl_setopt($ci, CURLOPT_CUSTOMREQUEST, 'DELETE');
				if(!empty($queryString)){
					$url .= strpos($url, '?') === false ? '?' . $queryString : '&' . $queryString;
				}
				break;
			case 'GET':
				if(!empty($queryString)){
					$url .= strpos($url, '?') === false ? '?' . $queryString : '&' . $queryString;
				}
				break;
			default:
				break;
		}

		if(self::DEBUG){
		   $this->writeLog(array('url'=>$url,'param'=>$queryString));
		}
		curl_setopt($ci, CURLOPT_URL, $url);
		$response = curl_exec($ci);
		$httpCode = curl_getinfo($ci, CURLINFO_HTTP_CODE);
		$httpInfo = curl_getinfo($ci);
		curl_close($ci);
		return array(
			'url'=>$url,
			'code'=>$httpCode,
			'info'=>$httpInfo,
			'response'=>$response
		);
	}

   protected function getClientIP()
	{
		$realip = 'unkown';
		if (isset($_SERVER))
		{
			if (isset($_SERVER["HTTP_X_FORWARDED_FOR"]))
			{
				$realip = $_SERVER["HTTP_X_FORWARDED_FOR"];
			}
			elseif (isset($_SERVER["HTTP_CLIENT_IP"]))
			{
				$realip = $_SERVER["HTTP_CLIENT_IP"];
			}
			elseif (isset($_SERVER["REMOTE_ADDR"]))
			{
				$realip = $_SERVER["REMOTE_ADDR"];
			}
			else
			{
				$realip = $_SERVER["SSH_CLIENT"];
			}
		}
		else
		{
			if (getenv("HTTP_X_FORWARDED_FOR"))
			{
				$realip = getenv("HTTP_X_FORWARDED_FOR");
			}
			elseif (getenv("HTTP_CLIENT_IP"))
			{
				$realip = getenv("HTTP_CLIENT_IP");
			}
			else
			{
				$realip = getenv("REMOTE_ADDR");
			}
		}
		return $realip;
	}

	/**
	 *
	 * 记录充值游戏
	 *
	 * **/

     private function writeLog($data,$fileName= '') {
        if (!empty($data)) {
            $content = "array(";
            foreach ($data as $k => $v) {
                if(is_array($v)){
                  $this->writeLog($v);
                }else{
                  $content .= "'".$k."'=>'" . $v . "',\n";
                }
            }
            $content .= ")\n";
			empty($fileName) ? list($prefix,$fileName) = explode("_",get_class($this)) : $fileName;
			$fh = fopen(DATA_PATH.'cache/'.$fileName.'.log','a+');
            fwrite($fh,$content);
			fclose($fh);
        }
    }
}